﻿#pragma once

#include "df_macro.h"
#include "atom.h"

///内嵌引用计数
#define DF_PTR_REF_COUNT   private:df::AutoPtrBase into_Ptr_Member_;\
public:inline void PtrIncRef(){ into_Ptr_Member_.PtrIncRef(); }\
	inline int PtrDecRef(){ return into_Ptr_Member_.PtrDecRef(); }\
	inline void Ptr_Release(){ if (PtrDecRef() == 0)delete this; }

namespace df
{

	//////////////////侵入式智能指针(没有shared_ptr的重复引用缺陷)///////////////////////////

	///定制对象引用计数操作
	struct AutoPtrDel
	{
		template<class T>
		static void PtrRelease(T * & obj)
		{
			if (obj != nullptr && obj->PtrDecRef() == 0)
			{
				delete obj;
				obj = nullptr;
			}
		}

		template<class T>
		static void PtrInc(T * obj)
		{
			obj->PtrIncRef();
		}
	};

	///继承此类或定义成员PTR_REF_COUNT,实现内嵌引用计数
	class AutoPtrBase
	{
	private:
		//引用计数
		int ptrRefCount_ = 0;
		DF_DISABLE_COPY_ASSIGN(AutoPtrBase);
	public:
		inline AutoPtrBase()
		{
		}

		//引用+1
		inline void PtrIncRef()
		{
			AtomInc(&ptrRefCount_);
		}

		//引用-1
		inline int PtrDecRef()
		{
			return AtomDec(&ptrRefCount_);
		}
	};



	//智能指针
	template<class ObjT, class DelT = AutoPtrDel>
	class AutoPtr
	{
	private:
		//托管对象
		ObjT * objPtr_;

		template <class T, class U>
		friend class AutoPtr;

	public:
		inline AutoPtr() : objPtr_(nullptr)
		{
		}

		inline AutoPtr(const AutoPtr & ip)
		{
			//DF_ASSERT(ip.objPtr_ != nullptr);
			Set(ip);
		}

		template<class T>
		inline AutoPtr(const AutoPtr<T, DelT> & ip)
		{
			//DF_ASSERT(ip.objPtr_ != nullptr);

			Set(ip);
		}

		//右值构造,如编译器不支持可将此注释掉
		template<class T>
		inline AutoPtr(AutoPtr<T, DelT> && ip)
		{
			objPtr_ = ip.objPtr_;
			ip.objPtr_ = nullptr;
		}

		inline AutoPtr(ObjT * obj)
		{
			//DF_ASSERT(obj != nullptr);

			Set(obj);
		}


		//构造函数的第二参数传bool,将不在构造时自动增加引用计数
		inline AutoPtr(ObjT * obj, bool )
		{
			//DF_ASSERT(obj != nullptr);
			objPtr_ = obj;
		}


		inline ~AutoPtr()
		{
			DelT::PtrRelease(objPtr_);
		}

		//更改引用对象
		template<class T>
		inline void Reset(const AutoPtr<T, DelT> & ip)
		{
			//DF_ASSERT(objPtr_ != ip.objPtr_ && ip.objPtr_ != nullptr);

			if (objPtr_ == ip.objPtr_ || ip.objPtr_ == nullptr)
				return;

			DelT::PtrRelease(objPtr_);
			Set(ip);
		}
		inline void Reset(ObjT * obj)
		{
			//DF_ASSERT(obj != nullptr && objPtr_ != obj);

			if (objPtr_ == obj)
				return;

			DelT::PtrRelease(objPtr_);
			Set(obj);
		}

		//取对象指针
		inline ObjT * operator->() const
		{
			DF_ASSERT(objPtr_ != nullptr);
			return objPtr_;
		}

		//取对象指针
		inline ObjT & operator*()
		{
			DF_ASSERT(objPtr_ != nullptr);
			return *objPtr_;
		}

		inline AutoPtr & operator = (const AutoPtr & ip)
		{
			Reset(ip);
			return *this;
		}

		template<class T>
		inline AutoPtr & operator = (const AutoPtr<T, DelT> & ip)
		{
			Reset(ip);
			return *this;
		}

		template<class T>
		inline bool operator== (const AutoPtr<T, DelT> & ip)
		{
			return ip.objPtr_ == objPtr_;
		}

		inline bool operator== (ObjT * obj)
		{
			return objPtr_ == obj;
		}

		template<class T>
		inline bool operator!= (const AutoPtr<T, DelT> & ip)
		{
			return ip.objPtr_ != objPtr_;
		}

		inline bool operator!= (ObjT * obj)
		{
			return objPtr_ != obj;
		}

		inline AutoPtr & operator = (ObjT * obj)
		{
			Reset(obj);
			return *this;
		}

		inline ObjT * Get() const
		{
			return objPtr_;
		}

		inline ObjT * get() const
		{
			return objPtr_;
		}

		inline operator bool() const
		{
			return objPtr_ != nullptr;
		}

	private:

		template<class T>
		inline void Set(const AutoPtr<T, DelT> & ip)
		{
			DelT::PtrInc(ip.objPtr_);
			objPtr_ = ip.objPtr_;
		}

		inline void Set(ObjT * obj)
		{
			if (obj)
				DelT::PtrInc(obj);
			objPtr_ = obj;
		}

	};

}
